{
  "cells": [
    {
      "cell_type": "code",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2025-01-16T08:19:00.814422Z",
          "start_time": "2025-01-16T08:18:58.434336Z"
        },
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "jehousAZ5gNj",
        "outputId": "210115b4-22a3-49e4-edb6-5ad5f5281a12"
      },
      "source": [
        "import matplotlib as mpl\n",
        "import matplotlib.pyplot as plt\n",
        "%matplotlib inline\n",
        "import numpy as np\n",
        "import sklearn\n",
        "import pandas as pd\n",
        "import os\n",
        "import sys\n",
        "import time\n",
        "from tqdm.auto import tqdm\n",
        "import torch\n",
        "import torch.nn as nn\n",
        "import torch.nn.functional as F\n",
        "\n",
        "print(sys.version_info)\n",
        "for module in mpl, np, pd, sklearn, torch:\n",
        "    print(module.__name__, module.__version__)\n",
        "\n",
        "device = torch.device(\"cuda:0\") if torch.cuda.is_available() else torch.device(\"cpu\")\n",
        "print(device)\n"
      ],
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "sys.version_info(major=3, minor=11, micro=11, releaselevel='final', serial=0)\n",
            "matplotlib 3.10.0\n",
            "numpy 1.26.4\n",
            "pandas 2.2.2\n",
            "sklearn 1.6.0\n",
            "torch 2.5.1+cu121\n",
            "cuda:0\n"
          ]
        }
      ],
      "execution_count": 1
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "UB3SguXq5gNn"
      },
      "source": [
        "## 加载数据"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2025-01-16T08:22:48.713405Z",
          "start_time": "2025-01-16T08:22:48.682256Z"
        },
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "4HtzYC8v5gNo",
        "outputId": "da0bcb5f-0290-495d-f7ea-2deaa6fb2e92"
      },
      "source": [
        "from torchvision import datasets\n",
        "from torchvision.transforms import ToTensor\n",
        "\n",
        "# fashion_mnist图像分类数据集\n",
        "train_ds = datasets.FashionMNIST(\n",
        "    root=\"data\",\n",
        "    train=True,\n",
        "    download=True,\n",
        "    transform=ToTensor()\n",
        ")\n",
        "\n",
        "test_ds = datasets.FashionMNIST(\n",
        "    root=\"data\",\n",
        "    train=False,\n",
        "    download=True,\n",
        "    transform=ToTensor()\n",
        ")\n",
        "\n",
        "# torchvision 数据集里没有提供训练集和验证集的划分\n",
        "# 当然也可以用 torch.utils.data.Dataset 实现人为划分\n",
        "# 从数据集到dataloader\n",
        "train_loader = torch.utils.data.DataLoader(train_ds, batch_size=16, shuffle=True)\n",
        "val_loader = torch.utils.data.DataLoader(test_ds, batch_size=16, shuffle=False)"
      ],
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Downloading http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/train-images-idx3-ubyte.gz\n",
            "Downloading http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/train-images-idx3-ubyte.gz to data/FashionMNIST/raw/train-images-idx3-ubyte.gz\n"
          ]
        },
        {
          "output_type": "stream",
          "name": "stderr",
          "text": [
            "100%|██████████| 26.4M/26.4M [00:02<00:00, 9.32MB/s]\n"
          ]
        },
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Extracting data/FashionMNIST/raw/train-images-idx3-ubyte.gz to data/FashionMNIST/raw\n",
            "\n",
            "Downloading http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/train-labels-idx1-ubyte.gz\n",
            "Downloading http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/train-labels-idx1-ubyte.gz to data/FashionMNIST/raw/train-labels-idx1-ubyte.gz\n"
          ]
        },
        {
          "output_type": "stream",
          "name": "stderr",
          "text": [
            "100%|██████████| 29.5k/29.5k [00:00<00:00, 199kB/s]\n"
          ]
        },
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Extracting data/FashionMNIST/raw/train-labels-idx1-ubyte.gz to data/FashionMNIST/raw\n",
            "\n",
            "Downloading http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/t10k-images-idx3-ubyte.gz\n",
            "Downloading http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/t10k-images-idx3-ubyte.gz to data/FashionMNIST/raw/t10k-images-idx3-ubyte.gz\n"
          ]
        },
        {
          "output_type": "stream",
          "name": "stderr",
          "text": [
            "100%|██████████| 4.42M/4.42M [00:01<00:00, 3.69MB/s]\n"
          ]
        },
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Extracting data/FashionMNIST/raw/t10k-images-idx3-ubyte.gz to data/FashionMNIST/raw\n",
            "\n",
            "Downloading http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/t10k-labels-idx1-ubyte.gz\n",
            "Downloading http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/t10k-labels-idx1-ubyte.gz to data/FashionMNIST/raw/t10k-labels-idx1-ubyte.gz\n"
          ]
        },
        {
          "output_type": "stream",
          "name": "stderr",
          "text": [
            "100%|██████████| 5.15k/5.15k [00:00<00:00, 6.29MB/s]"
          ]
        },
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Extracting data/FashionMNIST/raw/t10k-labels-idx1-ubyte.gz to data/FashionMNIST/raw\n",
            "\n"
          ]
        },
        {
          "output_type": "stream",
          "name": "stderr",
          "text": [
            "\n"
          ]
        }
      ],
      "execution_count": 2
    },
    {
      "cell_type": "code",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2025-01-16T08:23:41.556696Z",
          "start_time": "2025-01-16T08:23:38.810294Z"
        },
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "PdeRl8lT5gNp",
        "outputId": "68f9cc20-e8c0-44d9-fff2-e3176a7cc1db"
      },
      "source": [
        "from torchvision.transforms import Normalize\n",
        "\n",
        "# 遍历train_ds得到每张图片，计算每个通道的均值和方差\n",
        "def cal_mean_std(ds):\n",
        "    mean = 0.\n",
        "    std = 0.\n",
        "    for img, _ in ds: # 遍历每张图片,img.shape=[1,28,28]\n",
        "        mean += img.mean(dim=(1, 2))\n",
        "        std += img.std(dim=(1, 2))\n",
        "    mean /= len(ds)\n",
        "    std /= len(ds)\n",
        "    return mean, std\n",
        "\n",
        "\n",
        "print(cal_mean_std(train_ds))\n",
        "# 0.2860， 0.3205\n",
        "transforms = nn.Sequential(\n",
        "    Normalize([0.2860], [0.3205]) # 这里的均值和标准差是通过train_ds计算得到的\n",
        ")\n"
      ],
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "(tensor([0.2860]), tensor([0.3205]))\n"
          ]
        }
      ],
      "execution_count": 3
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "P7TOuuqd5gNq"
      },
      "source": [
        "## 定义模型\n",
        "\n",
        "这里我们没有用`nn.Linear`的默认初始化，而是采用了xavier均匀分布去初始化全连接层的权重\n",
        "\n",
        "xavier初始化出自论文 《Understanding the difficulty of training deep feedforward neural networks》，适用于使用`tanh`和`sigmoid`激活函数的方法。当然，我们这里的模型采用的是`relu`激活函数，采用He初始化（何凯明初始化）会更加合适。感兴趣的同学可以自己动手修改并比对效果。\n",
        "\n",
        "|神经网络层数|初始化方式|early stop at epoch| val_loss | vla_acc|\n",
        "|-|-|-|-|-|\n",
        "|20|默认|\n",
        "|20|xaviier_uniform|\n",
        "|20|he_uniform|\n",
        "|...|\n",
        "\n",
        "He初始化出自论文 《Delving deep into rectifiers: Surpassing human-level performance on ImageNet classification》"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2025-01-16T08:24:43.639389Z",
          "start_time": "2025-01-16T08:24:43.631382Z"
        },
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "eCWte6if5gNq",
        "outputId": "cbacabb3-5e1a-4f21-9950-6cebd12e83a1"
      },
      "source": [
        "class NeuralNetwork(nn.Module):\n",
        "    def __init__(self, layers_num=2):\n",
        "        super().__init__()\n",
        "        self.transforms = transforms # 预处理层，标准化\n",
        "        self.flatten = nn.Flatten()\n",
        "        # 多加几层\n",
        "        self.linear_relu_stack = nn.Sequential(\n",
        "            nn.Linear(28 * 28, 100),\n",
        "            nn.ReLU(),\n",
        "        )\n",
        "        # 加19层\n",
        "        for i in range(1, layers_num):\n",
        "            self.linear_relu_stack.add_module(f\"Linear_{i}\", nn.Linear(100, 100))\n",
        "            self.linear_relu_stack.add_module(f\"relu\", nn.ReLU())\n",
        "        # 输出层\n",
        "        self.linear_relu_stack.add_module(\"Output Layer\", nn.Linear(100, 10))\n",
        "\n",
        "        # 初始化权重\n",
        "        self.init_weights()\n",
        "\n",
        "    def init_weights(self):\n",
        "        \"\"\"使用 xavier 均匀分布来初始化全连接层的权重 W\"\"\"\n",
        "        # print('''初始化权重''')\n",
        "        for m in self.modules():\n",
        "            # print(m)\n",
        "            # print('-'*50)\n",
        "            if isinstance(m, nn.Linear):#判断m是否为全连接层\n",
        "                # https://pytorch.org/docs/stable/nn.init.html\n",
        "                nn.init.xavier_uniform_(m.weight) # xavier 均匀分布初始化权重\n",
        "                nn.init.zeros_(m.bias) # 全零初始化偏置项\n",
        "        # print('''初始化权重完成''')\n",
        "    def forward(self, x):\n",
        "        # x.shape [batch size, 1, 28, 28]\n",
        "        x = self.transforms(x) #标准化\n",
        "        x = self.flatten(x)\n",
        "        # 展平后 x.shape [batch size, 28 * 28]\n",
        "        logits = self.linear_relu_stack(x)\n",
        "        # logits.shape [batch size, 10]\n",
        "        return logits\n",
        "total=0\n",
        "for idx, (key, value) in enumerate(NeuralNetwork(20).named_parameters()):\n",
        "    print(f\"Linear_{idx // 2:>02}\\tparamerters num: {np.prod(value.shape)}\") #np.prod是计算张量的元素个数\n",
        "    print(f\"Linear_{idx // 2:>02}\\tshape: {value.shape}\")\n",
        "    total+=np.prod(value.shape)\n",
        "total"
      ],
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Linear_00\tparamerters num: 78400\n",
            "Linear_00\tshape: torch.Size([100, 784])\n",
            "Linear_00\tparamerters num: 100\n",
            "Linear_00\tshape: torch.Size([100])\n",
            "Linear_01\tparamerters num: 10000\n",
            "Linear_01\tshape: torch.Size([100, 100])\n",
            "Linear_01\tparamerters num: 100\n",
            "Linear_01\tshape: torch.Size([100])\n",
            "Linear_02\tparamerters num: 10000\n",
            "Linear_02\tshape: torch.Size([100, 100])\n",
            "Linear_02\tparamerters num: 100\n",
            "Linear_02\tshape: torch.Size([100])\n",
            "Linear_03\tparamerters num: 10000\n",
            "Linear_03\tshape: torch.Size([100, 100])\n",
            "Linear_03\tparamerters num: 100\n",
            "Linear_03\tshape: torch.Size([100])\n",
            "Linear_04\tparamerters num: 10000\n",
            "Linear_04\tshape: torch.Size([100, 100])\n",
            "Linear_04\tparamerters num: 100\n",
            "Linear_04\tshape: torch.Size([100])\n",
            "Linear_05\tparamerters num: 10000\n",
            "Linear_05\tshape: torch.Size([100, 100])\n",
            "Linear_05\tparamerters num: 100\n",
            "Linear_05\tshape: torch.Size([100])\n",
            "Linear_06\tparamerters num: 10000\n",
            "Linear_06\tshape: torch.Size([100, 100])\n",
            "Linear_06\tparamerters num: 100\n",
            "Linear_06\tshape: torch.Size([100])\n",
            "Linear_07\tparamerters num: 10000\n",
            "Linear_07\tshape: torch.Size([100, 100])\n",
            "Linear_07\tparamerters num: 100\n",
            "Linear_07\tshape: torch.Size([100])\n",
            "Linear_08\tparamerters num: 10000\n",
            "Linear_08\tshape: torch.Size([100, 100])\n",
            "Linear_08\tparamerters num: 100\n",
            "Linear_08\tshape: torch.Size([100])\n",
            "Linear_09\tparamerters num: 10000\n",
            "Linear_09\tshape: torch.Size([100, 100])\n",
            "Linear_09\tparamerters num: 100\n",
            "Linear_09\tshape: torch.Size([100])\n",
            "Linear_10\tparamerters num: 10000\n",
            "Linear_10\tshape: torch.Size([100, 100])\n",
            "Linear_10\tparamerters num: 100\n",
            "Linear_10\tshape: torch.Size([100])\n",
            "Linear_11\tparamerters num: 10000\n",
            "Linear_11\tshape: torch.Size([100, 100])\n",
            "Linear_11\tparamerters num: 100\n",
            "Linear_11\tshape: torch.Size([100])\n",
            "Linear_12\tparamerters num: 10000\n",
            "Linear_12\tshape: torch.Size([100, 100])\n",
            "Linear_12\tparamerters num: 100\n",
            "Linear_12\tshape: torch.Size([100])\n",
            "Linear_13\tparamerters num: 10000\n",
            "Linear_13\tshape: torch.Size([100, 100])\n",
            "Linear_13\tparamerters num: 100\n",
            "Linear_13\tshape: torch.Size([100])\n",
            "Linear_14\tparamerters num: 10000\n",
            "Linear_14\tshape: torch.Size([100, 100])\n",
            "Linear_14\tparamerters num: 100\n",
            "Linear_14\tshape: torch.Size([100])\n",
            "Linear_15\tparamerters num: 10000\n",
            "Linear_15\tshape: torch.Size([100, 100])\n",
            "Linear_15\tparamerters num: 100\n",
            "Linear_15\tshape: torch.Size([100])\n",
            "Linear_16\tparamerters num: 10000\n",
            "Linear_16\tshape: torch.Size([100, 100])\n",
            "Linear_16\tparamerters num: 100\n",
            "Linear_16\tshape: torch.Size([100])\n",
            "Linear_17\tparamerters num: 10000\n",
            "Linear_17\tshape: torch.Size([100, 100])\n",
            "Linear_17\tparamerters num: 100\n",
            "Linear_17\tshape: torch.Size([100])\n",
            "Linear_18\tparamerters num: 10000\n",
            "Linear_18\tshape: torch.Size([100, 100])\n",
            "Linear_18\tparamerters num: 100\n",
            "Linear_18\tshape: torch.Size([100])\n",
            "Linear_19\tparamerters num: 10000\n",
            "Linear_19\tshape: torch.Size([100, 100])\n",
            "Linear_19\tparamerters num: 100\n",
            "Linear_19\tshape: torch.Size([100])\n",
            "Linear_20\tparamerters num: 1000\n",
            "Linear_20\tshape: torch.Size([10, 100])\n",
            "Linear_20\tparamerters num: 10\n",
            "Linear_20\tshape: torch.Size([10])\n"
          ]
        },
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "271410"
            ]
          },
          "metadata": {},
          "execution_count": 4
        }
      ],
      "execution_count": 4
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "tensor([[1., 0., 0., 0., 0.],\n",
              "        [0., 1., 0., 0., 0.],\n",
              "        [0., 0., 1., 0., 0.]])"
            ]
          },
          "metadata": {},
          "execution_count": 5
        }
      ],
      "source": [
        "w = torch.empty(3, 5)\n",
        "nn.init.eye_(w)"
      ],
      "metadata": {
        "ExecuteTime": {
          "end_time": "2024-07-18T08:14:01.335144900Z",
          "start_time": "2024-07-18T08:14:01.295167700Z"
        },
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "TBECF61v5gNr",
        "outputId": "b062c6d5-2982-42b4-f919-c420cb64b045"
      }
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "FARWTjHl5gNr"
      },
      "source": [
        "## 训练"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "metadata": {
        "ExecuteTime": {
          "end_time": "2024-07-18T08:18:23.231667700Z",
          "start_time": "2024-07-18T08:18:22.410532400Z"
        },
        "id": "Zt4asFVu5gNs"
      },
      "outputs": [],
      "source": [
        "from sklearn.metrics import accuracy_score\n",
        "\n",
        "@torch.no_grad()\n",
        "def evaluating(model, dataloader, loss_fct):\n",
        "    loss_list = []\n",
        "    pred_list = []\n",
        "    label_list = []\n",
        "    for datas, labels in dataloader:\n",
        "        datas = datas.to(device)\n",
        "        labels = labels.to(device)\n",
        "        # 前向计算\n",
        "        logits = model(datas)\n",
        "        loss = loss_fct(logits, labels)         # 验证集损失\n",
        "        loss_list.append(loss.item())\n",
        "\n",
        "        preds = logits.argmax(axis=-1)    # 验证集预测\n",
        "        pred_list.extend(preds.cpu().numpy().tolist())\n",
        "        label_list.extend(labels.cpu().numpy().tolist())\n",
        "\n",
        "    acc = accuracy_score(label_list, pred_list)\n",
        "    return np.mean(loss_list), acc\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "metadata": {
        "ExecuteTime": {
          "end_time": "2024-07-18T08:18:32.648585100Z",
          "start_time": "2024-07-18T08:18:32.401627500Z"
        },
        "id": "EykLoAbf5gNs"
      },
      "outputs": [],
      "source": [
        "from torch.utils.tensorboard import SummaryWriter\n",
        "\n",
        "\n",
        "class TensorBoardCallback:\n",
        "    def __init__(self, log_dir, flush_secs=10):\n",
        "        \"\"\"\n",
        "        Args:\n",
        "            log_dir (str): dir to write log.\n",
        "            flush_secs (int, optional): write to dsk each flush_secs seconds. Defaults to 10.\n",
        "        \"\"\"\n",
        "        self.writer = SummaryWriter(log_dir=log_dir, flush_secs=flush_secs)\n",
        "\n",
        "    def draw_model(self, model, input_shape):\n",
        "        self.writer.add_graph(model, input_to_model=torch.randn(input_shape))\n",
        "\n",
        "    def add_loss_scalars(self, step, loss, val_loss):\n",
        "        self.writer.add_scalars(\n",
        "            main_tag=\"training/loss\",\n",
        "            tag_scalar_dict={\"loss\": loss, \"val_loss\": val_loss},\n",
        "            global_step=step,\n",
        "            )\n",
        "\n",
        "    def add_acc_scalars(self, step, acc, val_acc):\n",
        "        self.writer.add_scalars(\n",
        "            main_tag=\"training/accuracy\",\n",
        "            tag_scalar_dict={\"accuracy\": acc, \"val_accuracy\": val_acc},\n",
        "            global_step=step,\n",
        "        )\n",
        "\n",
        "    def add_lr_scalars(self, step, learning_rate):\n",
        "        self.writer.add_scalars(\n",
        "            main_tag=\"training/learning_rate\",\n",
        "            tag_scalar_dict={\"learning_rate\": learning_rate},\n",
        "            global_step=step,\n",
        "\n",
        "        )\n",
        "\n",
        "    def __call__(self, step, **kwargs):\n",
        "        # add loss\n",
        "        loss = kwargs.pop(\"loss\", None)\n",
        "        val_loss = kwargs.pop(\"val_loss\", None)\n",
        "        if loss is not None and val_loss is not None:\n",
        "            self.add_loss_scalars(step, loss, val_loss)\n",
        "        # add acc\n",
        "        acc = kwargs.pop(\"acc\", None)\n",
        "        val_acc = kwargs.pop(\"val_acc\", None)\n",
        "        if acc is not None and val_acc is not None:\n",
        "            self.add_acc_scalars(step, acc, val_acc)\n",
        "        # add lr\n",
        "        learning_rate = kwargs.pop(\"lr\", None)\n",
        "        if learning_rate is not None:\n",
        "            self.add_lr_scalars(step, learning_rate)\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "metadata": {
        "ExecuteTime": {
          "end_time": "2024-07-18T08:18:38.910670Z",
          "start_time": "2024-07-18T08:18:38.904974600Z"
        },
        "id": "iJvlg-8y5gNt"
      },
      "outputs": [],
      "source": [
        "class SaveCheckpointsCallback:\n",
        "    def __init__(self, save_dir, save_step=5000, save_best_only=True):\n",
        "        \"\"\"\n",
        "        Save checkpoints each save_epoch epoch.\n",
        "        We save checkpoint by epoch in this implementation.\n",
        "        Usually, training scripts with pytorch evaluating model and save checkpoint by step.\n",
        "\n",
        "        Args:\n",
        "            save_dir (str): dir to save checkpoint\n",
        "            save_epoch (int, optional): the frequency to save checkpoint. Defaults to 1.\n",
        "            save_best_only (bool, optional): If True, only save the best model or save each model at every epoch.\n",
        "        \"\"\"\n",
        "        self.save_dir = save_dir\n",
        "        self.save_step = save_step\n",
        "        self.save_best_only = save_best_only\n",
        "        self.best_metrics = -1\n",
        "\n",
        "        # mkdir\n",
        "        if not os.path.exists(self.save_dir):\n",
        "            os.mkdir(self.save_dir)\n",
        "\n",
        "    def __call__(self, step, state_dict, metric=None):\n",
        "        if step % self.save_step > 0:\n",
        "            return\n",
        "\n",
        "        if self.save_best_only:\n",
        "            assert metric is not None\n",
        "            if metric >= self.best_metrics:\n",
        "                # save checkpoints\n",
        "                torch.save(state_dict, os.path.join(self.save_dir, \"best.ckpt\"))\n",
        "                # update best metrics\n",
        "                self.best_metrics = metric\n",
        "        else:\n",
        "            torch.save(state_dict, os.path.join(self.save_dir, f\"{step}.ckpt\"))\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "metadata": {
        "ExecuteTime": {
          "end_time": "2024-07-18T08:18:43.022006800Z",
          "start_time": "2024-07-18T08:18:43.014428900Z"
        },
        "id": "HsUG__Gg5gNt"
      },
      "outputs": [],
      "source": [
        "class EarlyStopCallback:\n",
        "    def __init__(self, patience=5, min_delta=0.01):\n",
        "        \"\"\"\n",
        "\n",
        "        Args:\n",
        "            patience (int, optional): Number of epochs with no improvement after which training will be stopped.. Defaults to 5.\n",
        "            min_delta (float, optional): Minimum change in the monitored quantity to qualify as an improvement, i.e. an absolute\n",
        "                change of less than min_delta, will count as no improvement. Defaults to 0.01.\n",
        "        \"\"\"\n",
        "        self.patience = patience\n",
        "        self.min_delta = min_delta\n",
        "        self.best_metric = -1\n",
        "        self.counter = 0\n",
        "\n",
        "    def __call__(self, metric):\n",
        "        if metric >= self.best_metric + self.min_delta:\n",
        "            # update best metric\n",
        "            self.best_metric = metric\n",
        "            # reset counter\n",
        "            self.counter = 0\n",
        "        else:\n",
        "            self.counter += 1\n",
        "\n",
        "    @property\n",
        "    def early_stop(self):\n",
        "        return self.counter >= self.patience\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "metadata": {
        "ExecuteTime": {
          "end_time": "2024-07-18T08:19:20.271204500Z",
          "start_time": "2024-07-18T08:19:20.261309700Z"
        },
        "id": "trbNVnh05gNt"
      },
      "outputs": [],
      "source": [
        "# 训练\n",
        "def training(\n",
        "    model,\n",
        "    train_loader,\n",
        "    val_loader,\n",
        "    epoch,\n",
        "    loss_fct,\n",
        "    optimizer,\n",
        "    tensorboard_callback=None,\n",
        "    save_ckpt_callback=None,\n",
        "    early_stop_callback=None,\n",
        "    eval_step=500,\n",
        "    ):\n",
        "    record_dict = {\n",
        "        \"train\": [],\n",
        "        \"val\": []\n",
        "    }\n",
        "\n",
        "    global_step = 0\n",
        "    model.train()\n",
        "    with tqdm(total=epoch * len(train_loader)) as pbar:\n",
        "        for epoch_id in range(epoch):\n",
        "            # training\n",
        "            for datas, labels in train_loader:\n",
        "                datas = datas.to(device)\n",
        "                labels = labels.to(device)\n",
        "                # 梯度清空\n",
        "                optimizer.zero_grad()\n",
        "                # 模型前向计算\n",
        "                logits = model(datas)\n",
        "                # 计算损失\n",
        "                loss = loss_fct(logits, labels)\n",
        "                # 梯度回传\n",
        "                loss.backward()\n",
        "                # 调整优化器，包括学习率的变动等\n",
        "                optimizer.step()\n",
        "                preds = logits.argmax(axis=-1)\n",
        "\n",
        "                acc = accuracy_score(labels.cpu().numpy(), preds.cpu().numpy())\n",
        "                loss = loss.cpu().item()\n",
        "                # record\n",
        "\n",
        "                record_dict[\"train\"].append({\n",
        "                    \"loss\": loss, \"acc\": acc, \"step\": global_step\n",
        "                })\n",
        "\n",
        "                # evaluating\n",
        "                if global_step % eval_step == 0:\n",
        "                    model.eval()\n",
        "                    val_loss, val_acc = evaluating(model, val_loader, loss_fct)\n",
        "                    record_dict[\"val\"].append({\n",
        "                        \"loss\": val_loss, \"acc\": val_acc, \"step\": global_step\n",
        "                    })\n",
        "                    model.train()\n",
        "\n",
        "                    # 1. 使用 tensorboard 可视化\n",
        "                    if tensorboard_callback is not None:\n",
        "                        tensorboard_callback(\n",
        "                            global_step,\n",
        "                            loss=loss, val_loss=val_loss,\n",
        "                            acc=acc, val_acc=val_acc,\n",
        "                            lr=optimizer.param_groups[0][\"lr\"],\n",
        "                            )\n",
        "\n",
        "                    # 2. 保存模型权重 save model checkpoint\n",
        "                    if save_ckpt_callback is not None:\n",
        "                        save_ckpt_callback(global_step, model.state_dict(), metric=val_acc)\n",
        "\n",
        "                    # 3. 早停 Early Stop\n",
        "                    if early_stop_callback is not None:\n",
        "                        early_stop_callback(val_acc)\n",
        "                        if early_stop_callback.early_stop:\n",
        "                            print(f\"Early stop at epoch {epoch_id} / global_step {global_step}\")\n",
        "                            return record_dict\n",
        "\n",
        "                # udate step\n",
        "                global_step += 1\n",
        "                pbar.update(1)\n",
        "                pbar.set_postfix({\"epoch\": epoch_id})\n",
        "\n",
        "    return record_dict\n",
        "\n",
        "\n",
        "epoch = 100\n",
        "\n",
        "model = NeuralNetwork(layers_num=10)\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "outputs": [],
      "source": [
        "# 1. 定义损失函数 采用交叉熵损失\n",
        "loss_fct = nn.CrossEntropyLoss()\n",
        "# 2. 定义优化器 采用SGD\n",
        "# Optimizers specified in the torch.optim package\n",
        "optimizer = torch.optim.SGD(model.parameters(), lr=0.001, momentum=0.9)\n",
        "\n",
        "# 1. tensorboard 可视化\n",
        "tensorboard_callback = TensorBoardCallback(\"runs\")\n",
        "tensorboard_callback.draw_model(model, [1, 28, 28])\n",
        "# 2. save best\n",
        "save_ckpt_callback = SaveCheckpointsCallback(\"checkpoints\", save_best_only=True)\n",
        "# 3. early stop\n",
        "early_stop_callback = EarlyStopCallback(patience=10, min_delta=0.001)\n",
        "\n",
        "model = model.to(device)"
      ],
      "metadata": {
        "ExecuteTime": {
          "end_time": "2024-07-18T08:19:45.450320900Z",
          "start_time": "2024-07-18T08:19:45.175435500Z"
        },
        "id": "GoboF3wO5gNu"
      }
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "outputs": [
        {
          "data": {
            "application/vnd.jupyter.widget-view+json": {
              "model_id": "efba2d81bc3341f98555038b1ce3cc7a",
              "version_major": 2,
              "version_minor": 0
            },
            "text/plain": [
              "  0%|          | 0/375000 [00:00<?, ?it/s]"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "record = training(\n",
        "    model,\n",
        "    train_loader,\n",
        "    val_loader,\n",
        "    epoch,\n",
        "    loss_fct,\n",
        "    optimizer,\n",
        "    tensorboard_callback=None,\n",
        "    save_ckpt_callback=save_ckpt_callback,\n",
        "    early_stop_callback=early_stop_callback,\n",
        "    eval_step=len(train_loader)\n",
        "    )"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 49,
          "referenced_widgets": [
            "efba2d81bc3341f98555038b1ce3cc7a",
            "d501445c7b4549ed8feed6fa108f0d7b",
            "0b0af2b452f742d9b6d0522b8b1a46f2",
            "337778d022fa43afbfd0c67036e47ac5",
            "fe50520cbec64f439a8fbe8498628c4e",
            "118baf40455b440abddde0c225d73340",
            "f58b496d76f74578b0d0570db2420960",
            "33ee1352242e4838b2c481cccf494dc1",
            "92ad6cbc296845bba847b1248266ab65",
            "53321e7b2dca40f1be907eda57ded9e2",
            "b1b4019fc9e84c838bd928238f89f382"
          ]
        },
        "id": "sBAl06Wd5gNu",
        "outputId": "f5f7f312-53d2-4c61-cdea-25a0f64ecb60"
      }
    },
    {
      "cell_type": "code",
      "execution_count": 15,
      "metadata": {
        "ExecuteTime": {
          "end_time": "2023-11-17T13:06:44.722561800Z",
          "start_time": "2023-11-17T13:06:44.373481400Z"
        },
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 465
        },
        "id": "FteuGime5gNu",
        "outputId": "28fb1253-e31e-4e70-d366-c378e04a1b61"
      },
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "<Figure size 1200x500 with 2 Axes>"
            ],
            "image/png": "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Sj0AIrJNSUkJ5s+fj1dffRV33nkn6urqsHv3bixYsACFhYWora3Fhx9+CADw9/eHwWDAjBkzkJSUhN27d0OpVOLFF1/E7bffjqNHj0KtVgMA0tPT4ebmhoyMDBQUFGDRokUICAjASy+9JOXLJSIicjm81hO5DibmRE6qpKQEra2tuOuuuzB48GAAwOjRowEA7u7u0Ov10Gq11uPXrVsHk8mEf/7zn5DJZACADz/8EH5+fsjIyEBKSgoAQK1W44MPPoCHhwfi4uLwhz/8AU8//TRWr14NuZyTbIiIiPoKr/VEroP/84ic1NixYzFt2jSMHj0a99xzD9577z1UVVV1evyRI0eQn58Pb29veHl5wcvLC/7+/mhubsbp06fbndfDw8P6fVJSEurr61FUVNSrr4eIiIja47WeyHWwYk7kpBQKBdLS0rBnzx5s27YNb731Fp577jns27evw+Pr6+sRHx+PTz/99Kr7goKCenu4RERE1E281hO5DibmRE5MJpNh0qRJmDRpElauXInBgwfjiy++gFqthtFobHfsDTfcgA0bNiA4OBg+Pj6dnvPIkSNoamqCu7s7AGDv3r3w8vJCREREr74WIiIiuhqv9USugVPZiZzUvn378PLLL+PAgQMoLCzEpk2bUF5ejhEjRiAyMhJHjx5Fbm4uKioqYDAYcP/99yMwMBB33HEHdu/ejbNnzyIjIwOPP/44zp8/bz1vS0sLHnroIZw4cQJbtmzBqlWrsGTJEq45IyIi6mO81hO5DlbMiZyUj48Pdu3ahddffx21tbUYPHgw/vKXv2DmzJlISEhARkYGEhISUF9fjx07duCWW27Brl278Mwzz+Cuu+5CXV0dBg4ciGnTprX7VH3atGmIiorClClToNfrMX/+fDz//PPSvVAiIiIXxWs9keuQCSGE1IMgIsfw4IMPorq6Gps3b5Z6KERERNQLeK0nckycr0JEREREREQkISbmRERERERERBLiVHYiIiIiIiIiCbFiTkRERERERCQhJuZEREREREREEmJiTkRERERERCQhJuZEREREREREEmJiTkRERERERCQhJuZEREREREREEmJiTkRERERERCQhJuZEREREREREEmJiTkRERERERCSh/w9QbCxOPC6iNQAAAABJRU5ErkJggg==\n"
          },
          "metadata": {}
        }
      ],
      "source": [
        "#画线要注意的是损失是不一定在零到1之间的\n",
        "def plot_learning_curves(record_dict, sample_step=500):\n",
        "    # build DataFrame\n",
        "    train_df = pd.DataFrame(record_dict[\"train\"]).set_index(\"step\").iloc[::sample_step]\n",
        "    val_df = pd.DataFrame(record_dict[\"val\"]).set_index(\"step\")\n",
        "\n",
        "    # plot\n",
        "    fig_num = len(train_df.columns)\n",
        "    fig, axs = plt.subplots(1, fig_num, figsize=(6 * fig_num, 5))\n",
        "    for idx, item in enumerate(train_df.columns):\n",
        "        axs[idx].plot(train_df.index, train_df[item], label=f\"train_{item}\")\n",
        "        axs[idx].plot(val_df.index, val_df[item], label=f\"val_{item}\")\n",
        "        axs[idx].grid()\n",
        "        axs[idx].legend()\n",
        "        axs[idx].set_xlabel(\"step\")\n",
        "\n",
        "    plt.show()\n",
        "\n",
        "plot_learning_curves(record, sample_step=10000)  #横坐标是 steps"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 16,
      "metadata": {
        "ExecuteTime": {
          "end_time": "2024-04-24T03:29:22.432377300Z",
          "start_time": "2024-04-24T03:29:18.976354400Z"
        },
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "b8zIfc1E5gNv",
        "outputId": "91640ae2-a14c-4218-c8cb-52d12a88695c"
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stderr",
          "text": [
            "<ipython-input-16-282285e79dd9>:4: FutureWarning: You are using `torch.load` with `weights_only=False` (the current default value), which uses the default pickle module implicitly. It is possible to construct malicious pickle data which will execute arbitrary code during unpickling (See https://github.com/pytorch/pytorch/blob/main/SECURITY.md#untrusted-models for more details). In a future release, the default value for `weights_only` will be flipped to `True`. This limits the functions that could be executed during unpickling. Arbitrary objects will no longer be allowed to be loaded via this mode unless they are explicitly allowlisted by the user via `torch.serialization.add_safe_globals`. We recommend you start setting `weights_only=True` for any use case where you don't have full control of the loaded file. Please open an issue on GitHub for any issues related to this experimental feature.\n",
            "  model.load_state_dict(torch.load(\"checkpoints/best.ckpt\", map_location=\"cpu\"))\n"
          ]
        },
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "loss:     0.3944\n",
            "accuracy: 0.8862\n"
          ]
        }
      ],
      "source": [
        "# dataload for evaluating\n",
        "\n",
        "# load checkpoints\n",
        "model.load_state_dict(torch.load(\"checkpoints/best.ckpt\", map_location=\"cpu\"))\n",
        "\n",
        "model.eval()\n",
        "loss, acc = evaluating(model, val_loader, loss_fct)\n",
        "print(f\"loss:     {loss:.4f}\\naccuracy: {acc:.4f}\")"
      ]
    },
    {
      "cell_type": "code",
      "source": [],
      "metadata": {
        "id": "nk2SFrdkAz_E"
      },
      "execution_count": null,
      "outputs": []
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.10.8"
    },
    "orig_nbformat": 4,
    "colab": {
      "provenance": [],
      "gpuType": "T4"
    },
    "accelerator": "GPU",
    "widgets": {
      "application/vnd.jupyter.widget-state+json": {
        "efba2d81bc3341f98555038b1ce3cc7a": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "HBoxModel",
          "model_module_version": "1.5.0",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HBoxModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HBoxView",
            "box_style": "",
            "children": [
              "IPY_MODEL_d501445c7b4549ed8feed6fa108f0d7b",
              "IPY_MODEL_0b0af2b452f742d9b6d0522b8b1a46f2",
              "IPY_MODEL_337778d022fa43afbfd0c67036e47ac5"
            ],
            "layout": "IPY_MODEL_fe50520cbec64f439a8fbe8498628c4e"
          }
        },
        "d501445c7b4549ed8feed6fa108f0d7b": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "HTMLModel",
          "model_module_version": "1.5.0",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HTMLModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HTMLView",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_118baf40455b440abddde0c225d73340",
            "placeholder": "​",
            "style": "IPY_MODEL_f58b496d76f74578b0d0570db2420960",
            "value": " 26%"
          }
        },
        "0b0af2b452f742d9b6d0522b8b1a46f2": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "FloatProgressModel",
          "model_module_version": "1.5.0",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "FloatProgressModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "ProgressView",
            "bar_style": "danger",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_33ee1352242e4838b2c481cccf494dc1",
            "max": 375000,
            "min": 0,
            "orientation": "horizontal",
            "style": "IPY_MODEL_92ad6cbc296845bba847b1248266ab65",
            "value": 97500
          }
        },
        "337778d022fa43afbfd0c67036e47ac5": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "HTMLModel",
          "model_module_version": "1.5.0",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HTMLModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HTMLView",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_53321e7b2dca40f1be907eda57ded9e2",
            "placeholder": "​",
            "style": "IPY_MODEL_b1b4019fc9e84c838bd928238f89f382",
            "value": " 97500/375000 [17:20&lt;44:19, 104.34it/s, epoch=25]"
          }
        },
        "fe50520cbec64f439a8fbe8498628c4e": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "model_module_version": "1.2.0",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "118baf40455b440abddde0c225d73340": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "model_module_version": "1.2.0",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "f58b496d76f74578b0d0570db2420960": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "DescriptionStyleModel",
          "model_module_version": "1.5.0",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "DescriptionStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "description_width": ""
          }
        },
        "33ee1352242e4838b2c481cccf494dc1": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "model_module_version": "1.2.0",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "92ad6cbc296845bba847b1248266ab65": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "ProgressStyleModel",
          "model_module_version": "1.5.0",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "ProgressStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "bar_color": null,
            "description_width": ""
          }
        },
        "53321e7b2dca40f1be907eda57ded9e2": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "model_module_version": "1.2.0",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "b1b4019fc9e84c838bd928238f89f382": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "DescriptionStyleModel",
          "model_module_version": "1.5.0",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "DescriptionStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "description_width": ""
          }
        }
      }
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}